package com.stellar.circle.redis.post;

import cn.hutool.core.date.DateUtil;

import com.stellar.circle.redis.RedisCacheKey;
import com.stellar.core.util.DateFormatConstants;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneId;

import static com.stellar.circle.constants.ErrorCodeConstants.PIN_ORDER_CODE_GENERATE_ERROR;
import static com.stellar.core.util.ServiceExceptionUtil.exception;


/**
 * @Author Jqcc
 * @Version 1.0
 * @Date 2025/6/10
 * 置顶订单编号生成器
 */
@Component
public class PinOrderNoGenerator {


    @Resource
    private RedisTemplate<String, Long> redisTemplate;

    // 流水号的初始值
    private static final Long INITIAL_SEQUENCE = 1L;

    // 流水号的格式化长度 业务需求流水号5位，后期根据订单数做动态配置修改流水号长度，待优化
    private static final int SEQUENCE_FORMAT_LENGTH = 5;

    /**
     * 生成订单编号
     * 格式：LY_PIN + 日期（yyyyMMdd） + 流水号（5位，从001开始）
     *
     * @return 生成的订单编号 LY20250328001
     */
    public String genPinOrderNo() {
        ZoneId zoneId = ZoneId.of("Asia/Shanghai");
        LocalDateTime now = LocalDateTime.now(zoneId);
        String datePart = DateUtil.format(now, DateFormatConstants.DATE_FORMAT_YYYYMMDD);
        String sequencePart = genDistributePinOrderNo(now);
        return String.format("LY_PIN%s%s", datePart, sequencePart);
    }

    /**
     * 生成分布式流水号
     * 流水号从001开始，每天重置
     *
     * @return 流水号字符串（5位：001）
     */
    private String genDistributePinOrderNo(LocalDateTime now) {
        String redisKeyDate = DateUtil.format(now, DateFormatConstants.DATE_FORMAT_YYYYMMDD);
        String redisKey = String.format(RedisCacheKey.PIN_ORDER_NO.getCachePrefix(), redisKeyDate);
        Long sequence = redisTemplate.opsForValue().increment(redisKey, 1);
        if (sequence == null) {
            throw exception(PIN_ORDER_CODE_GENERATE_ERROR);
        }
        // 设置过期时间
        if (sequence == INITIAL_SEQUENCE) {
            redisTemplate.expire(redisKey, RedisCacheKey.PIN_ORDER_NO.getCacheTime(), RedisCacheKey.PIN_ORDER_NO.getCacheTimeUnit());
        }
        return String.format("%0" + SEQUENCE_FORMAT_LENGTH + "d", sequence);
    }
}